<template>
  <a-collapse>
    <a-collapse-item
      v-for="(item, index) in props.treeList"
      :key="item.id"
      :show-expand-icon="props.showExpandIcon"
      :class="classReturn(item)"
    >
      <template #header>
        <a-checkbox
          :key="index"
          :disabled="!props.isEdit"
          :model-value="item.checkedFlag === '1'"
          @change="handleAllCheckChange($event, index)"
          @click.stop
        >
        </a-checkbox>
        {{ item.name }}
      </template>
      <MenuTreeSelector
        v-if="item.children || item.menus"
        :tree-list="item.children ? item.children : item.menus"
        @change="handleTreeListChange"
        @check="handleCheck"
      ></MenuTreeSelector>
      <div v-if="item.resources && item.resources.length > 0">
        <a-checkbox
          v-for="itemr in item.resources"
          :key="item.id + '-' + itemr.id"
          class="margin-bottom-10"
          :label="itemr.name"
          :value="item.id + '-' + itemr.id"
          :model-value="itemr.checkedFlag === '1'"
          @change="handleResourcesChange($event, itemr.id, index)"
        >
          {{ itemr.name }}
        </a-checkbox>
      </div>
    </a-collapse-item>
  </a-collapse>
</template>

<script lang="ts" setup>
  import { defineProps, defineEmits, PropType, computed } from 'vue';
  import { TreeList } from './type';

  const props = defineProps({
    treeList: {
      type: Array as PropType<TreeList[]>,
      required: true,
    },
    showExpandIcon: {
      type: Boolean,
      default: () => {
        return true;
      },
    },
    isEdit: {
      type: Boolean,
      default: () => {
        return true;
      },
    },
  });
  const emit = defineEmits(['change', 'check']);
  const value = computed(() => props.treeList);

  // change事件
  const handleTreeListChange = (val: TreeList[]) => {
    val.forEach((item) => {
      value.value.forEach((ele) => {
        if (item.parentId === ele.id || item.portalId === ele.id) {
          if (ele.menus && ele.menus.length > 0) {
            ele.menus = val;
          }
          if (ele.children && ele.children.length > 0) {
            ele.children = val;
          }
          if (ele.resources && ele.resources.length > 0) {
            ele.resources = val;
          }
        }
      });
    });
    emit('change', value.value);
  };

  const classReturn = (item: TreeList) => {
    return {
      first: item.menus,
      second:
        Array.isArray(item.resources) &&
        item.resources.length === 0 &&
        item.children,
      three: !item.children && item.resources,
      four:
        !item.children &&
        Array.isArray(item.resources) &&
        item.resources.length === 0,
      five: item.menus && item.menus.length === 0,
    };
  };
  // 选中逻辑
  const handleCheck = (id: string) => {
    // 由子组件传入parentId 在当前组件的value中循环
    value.value.forEach((item) => {
      // 如果当前结点的id 等于 子组件传入的parentId
      // 选中当前结点
      // 继续向上查询，重复逻辑。找不到结束递归
      if (item.id === id) {
        item.checkedFlag = '1';
        emit('check', item.parentId || item.portalId);
      }
    });
    emit('change', value.value);
  };
  // 取消逻辑
  const handleCancel = (list: TreeList[]) => {
    // 将传入的数组循环，使得数组中每一项都取消选中
    list.forEach((item) => {
      // 数组当前项存在menus 并且长度大于0 那么当前结点属于门户结点
      if (item.menus && item.menus.length > 0) {
        // 递归调用handleCancel，传入当前项的menus
        handleCancel(item.menus);
      }
      // 数组当前项存在children 并且长度大于0 那么当前结点属于非叶子结点
      if (item.children && item.children.length > 0) {
        // 递归调用handleCancel，传入当前项的children
        handleCancel(item.children);
      }
      // 数组当前项不存在children并且存在resources，那么当前结点属于叶子结点，叶子结点下所有权限取消选中
      if (!item.children && item.resources) {
        item.resources.forEach((x) => {
          x.checkedFlag = '0';
        });
      }
      // 当前项取消选中
      item.checkedFlag = '0';
    });
    emit('change', value.value);
  };
  // 菜单选择
  const handleAllCheckChange = (
    val: boolean | (string | number | boolean)[],
    index: number
  ) => {
    if (val) {
      // 当前点击的结点选中
      value.value[index].checkedFlag = '1';
      // 如果resources长度不为0，那么说明该结点为叶子结点，根据需求选中叶子结点，所属权限全选
      if (
        value.value[index].resources &&
        value.value[index].resources.length > 0
      ) {
        value.value[index].resources.forEach((x) => {
          x.checkedFlag = '1';
        });
      }
      // 递归组件事件 传入当前结点的parentId
      emit('check', value.value[index].parentId || value.value[index].portalId);
    } else {
      // 当前点击的结点取消
      value.value[index].checkedFlag = '0';
      // 递归方法 传入当前结点下的子级 children或者resources
      const arr =
        value.value[index].menus ||
        value.value[index].children ||
        value.value[index].resources;
      handleCancel(arr as TreeList[]);
    }
  };
  // 资源选择
  const handleResourcesChange = (
    val: boolean | (string | number | boolean)[],
    id: string,
    index: number
  ) => {
    value.value[index].resources.forEach((item) => {
      if (item.id === id) {
        item.checkedFlag = val ? '1' : '0';
      }
    });
    if (value.value[index].resources.find((item) => item.checkedFlag === '1')) {
      value.value[index].checkedFlag = '1';
      // 递归组件事件 传入当前结点的parentId
      emit('check', value.value[index].parentId || value.value[index].portalId);
    }
    emit('change', value.value);
  };
</script>

<style lang="less" scoped>
  :deep(.arco-collapse-item-content) {
    padding-right: 0;
    background-color: #fff;
  }
  :deep(.arco-collapse-item-header) {
    background-color: transparent;
  }
  .first {
    background-color: var(--color-neutral-3) !important;
  }
  .second {
    background-color: var(--color-neutral-2) !important;
  }
  .three {
    background-color: var(--color-neutral-2) !important;
    :deep(.arco-collapse-item-content) {
      background-color: #fff !important;
    }
  }
  .four {
    background-color: var(--color-neutral-2) !important;
    :deep(.arco-collapse-item-content) {
      display: none !important;
    }
  }
  .five {
    background-color: var(--color-neutral-3) !important;
    :deep(.arco-collapse-item-content) {
      display: none !important;
    }
  }
</style>
